class AsyncProcess {
  constructor() {
    this.next;
  }
  static run(asyncProcess) {
    if (!asyncProcess instanceof AsyncProcess) {
      throw new Error("must be AsyncProcess type");
    }
    asyncProcess.process();
  }
  thenApply(asyncProcess) {
    if (!asyncProcess instanceof AsyncProcess) {
      throw new Error("must be AsyncProcess type");
    }
    this.next = asyncProcess;
    return this.next;
  }
  catch(errorHandel) {
    this.errorHandel = errorHandel;
    return this;
  }
  whenComplete(complete) {
    this.next=null;
    this.complete = complete;
    return this;
  }
  finally(finallyCallback){
    this.finallyCallback = finallyCallback;
    return this;
  }
  nextProcess(result) {
    let next=this.next;
    if (next != null) {
      try {
        this.next = null;
        next.process(result);
      } catch (error) {
        this.error(error);
      }
    } else {
      if (this.finallyCallback) {
        this.finallyCallback();
      }
      let complete = this.complete;
      if (complete){
        complete(result); 
      } 
    }
  }
  error(err) {
    
    let next = this;
    while (next.next != null) {
      next = next.next;
    }
    this.next = null;

    if (next.finallyCallback) {
      next.finallyCallback();
    }
    if (next.errorHandel) {
      next.errorHandel(err);
    }
  }
}
module.exports = AsyncProcess